package affd.converter;

import java.io.FileInputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.xmlrpc.server.PropertyHandlerMapping;
import org.apache.xmlrpc.server.XmlRpcServer;
import org.apache.xmlrpc.webserver.WebServer;

/**
 * A ConverterServer is document conversion server which uses JOD Converter to
 * convert documents to different formats.
 * 
 * @author Joteitti joteitti@cc.hut.fi
 *
 */
public class ConverterServer extends WebServer {
	
	public static final String CONFIGURATION_FILENAME = "config.txt";
	public static final String CONVERTER_KEY = "Converter";
	
	private static Logger logger;
	
	private static OfficeConverter officeConverter;
	
	static {
		// Create logger
		logger = Logger.getLogger("Converter");		
	}
	
	public static OfficeConverter getOfficeConverter() {
		return officeConverter;
	}
	
	/**
	 * Constructs a converter server.
	 * 
	 * @param port Server port to be used.
	 * @param officeHome Path to the OpenOffice executable.
	 * @param officePorts OpenOffice ports to be used.
	 * @param officeTimeout Timeout value for OpenOffice tasks. 
	 */
	public ConverterServer(int port, String officeHome, int[] officePorts, long officeTimeout) {
		super(port);
		
		// Create office converter
		officeConverter = new OfficeConverter(officeHome, officePorts, officeTimeout);
		
		// Configure xml rpc server
		try {
			XmlRpcServer xmlRpcServer = getXmlRpcServer();
			PropertyHandlerMapping handlerMapping = new PropertyHandlerMapping();
			handlerMapping.addHandler(CONVERTER_KEY, ConverterHandler.class);
			xmlRpcServer.setHandlerMapping(handlerMapping);
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Failed to construct converter xml rpc server.", e);
		}
	}
	
	/**
	 * Shutdowns the converter server.
	 */
	public void shutdown() {
		super.shutdown();
		
		logger.log(Level.INFO, "Shutting down the converter server.");
		
		// Shutdown office converter
		officeConverter.shutdown();
	}
	
	/**
	 * Gets the shutdown hook.
	 * 
	 * @return Runnable shutdown hook
	 */
	public Runnable getShutdownRunnable() {
		return new Runnable() {

			public void run() {
				shutdown();
			}
			
		};
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ConverterServer converterServer = null;
		try {
			// Load configuration
			Properties defaults = new Properties();
			defaults.setProperty("officeHome", "C:\\Program Files (x86)\\OpenOffice.org 3\\");
			defaults.setProperty("officePorts", "8109");
			defaults.setProperty("officeTimeout", "30000");
			defaults.setProperty("serverPort", "8110");
			
			Properties config = new Properties(defaults);
			try {
				config.load(new FileInputStream(CONFIGURATION_FILENAME));
			} catch(Exception e) {
				logger.log(Level.WARNING, "Couldn't load the configuration file.", e);
			}
			
			// Parse configuration
			int port = Integer.parseInt(config.getProperty("serverPort"));
			String officeHome = config.getProperty("officeHome").replace("\\\\", "\\");
			int officeTimeout = Integer.parseInt(config.getProperty("officeTimeout"));

			String[] tempOfficePorts = config.getProperty("officePorts").split(" ");
			int[] officePorts = new int[tempOfficePorts.length];
			for(int i = 0; i < officePorts.length; i++) {
				officePorts[i] = Integer.parseInt(tempOfficePorts[i]);
			}
			
			// Create converter server
			converterServer = new ConverterServer(port, officeHome, officePorts, officeTimeout);
			
			// Start web server
			converterServer.start();
			
			// Create a new shutdown hook
			Runtime.getRuntime().addShutdownHook(new Thread(converterServer.getShutdownRunnable()));
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Converter server failed to run.", e);
		}
	}

}
